package com.ssm.changeunit.persistance;
import com.ssm.changeunit.util.FileUtil;
import com.ssm.changeunit.Environment;
import java.io.IOException;
import java.sql.*;

/**
 *
 * @author EuiHyun
 */
public class DatabaseManager {
    private static DatabaseManager instance;
    private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver";  
    
    // ConnectionURL 
    private String connectionURL = "jdbc:derby:" + com.ssm.changeunit.Environment.DATABASE_NAME + ";";  
    
    private DatabaseManager () { 
    }
    
    /**
     * For Singleton Pattern
     * @return
     */
    public static DatabaseManager getInstance () { 
        if(instance == null)  
            instance = new DatabaseManager();  
        
        return instance; 
    } 
    
    /**
     * Connection을 얻어옵니다.
     * 
     * @return
     * @throws com.ssm.changeunit.persistance.PersistanceException
     */
    public Connection getConnection () throws PersistanceException { 
        try { 
            // Database driver loading 
            Class.forName(driver);  
            
            return DriverManager.getConnection(connectionURL); 
        } catch(ClassNotFoundException ex) { 
            // Driver class를 찾지 못한경우 
            throw new PersistanceException("Database driver 클래스를 찾을 수 없습니다.", ex); 
        } catch(SQLException ex) { 
            // 커넥션을 얻지 못한 경우 
            throw new PersistanceException("Connection을 얻을수 없습니다.", ex); 
        } 
    }
    
    /**
     * 데이터베이스가 존재하는지 검사하는 메서드
     * 
     * @return
     * @throws com.ssm.changeunit.persistance.PersistanceException
     */
    public boolean isExists() throws PersistanceException {        
        try { 
            // Database driver loading 
            Class.forName(driver);  
            
            DriverManager.getConnection(connectionURL); 
        
            return true;
        } catch(ClassNotFoundException ex) { 
            // Driver class를 찾지 못한경우 
            throw new PersistanceException("Database driver 클래스를 찾을 수 없습니다.", ex); 
        } catch(SQLException ex) { 
            // 커넥션을 얻지 못한 경우 
            
            // 데이터베이스가 없는 경우
            if(ex.getSQLState().equals("XJ004")) 
                return false;
            
            throw new PersistanceException("Connection을 얻을수 없습니다.", ex); 
        } 
    }
    
    /**
     * 데이터베이스를 초기화 합니다.
     * 
     * @throws com.ssm.changeunit.persistance.PersistanceException
     */
    public void initDatabase() throws PersistanceException {
        String databaseSchema = "";
        
        try {
            databaseSchema = FileUtil.readFromFile(Environment.DATABASE_SCHEMA_PATH);
        }
        catch(IOException ex) {
            throw new PersistanceException("Database 스키마를 찾을수 없습니다.", ex);
        }
        
        Connection conn = null;
        
        try { 
            // Database driver loading 
            Class.forName(driver);  
            
            conn = DriverManager.getConnection(connectionURL + "create=true"); 
        } catch(ClassNotFoundException ex) { 
            // Driver class를 찾지 못한경우 
            throw new PersistanceException("Database driver 클래스를 찾을 수 없습니다.", ex); 
        } catch(SQLException ex) { 
            // 커넥션을 얻지 못한 경우 
            throw new PersistanceException("Connection을 얻을수 없습니다.", ex); 
        } 
        
        // 검색 루틴 구현
        Statement stmt = null; 

        try {
            conn.setAutoCommit(true);   
            stmt = conn.createStatement(); 
            
            for(String subSql : databaseSchema.split("------")) 
                stmt.executeUpdate(subSql);
        }
        catch(SQLException e) { 
            throw new PersistanceException("Exception while executing DatabaseManager.initDatabase: "+ e, e);
        } 
        finally {
            if(stmt != null) 
                try { stmt.close(); }
                catch(Exception ignore) { }  
            if(conn != null) 
                try { conn.close(); } 
                catch(Exception ignore) { } 
        }
    }
}
